﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Kimd.Vision
{
    [Serializable]
    public class CircleNB : ShapeNB, ICloneable
    {
        public PointF Center;
        public float Radius;

        public CircleNB()
            : base()
        {
            TypeName = ShapeType.Circle;
        }

        public override void Draw(HWindow window, Graphics g, Func<PointF, PointF> pixel2Window, Func<float, float> lenConvert, bool disableEdit)
        {
            if (disableEdit || IsShowOnly)
            {
                window.SetColor(PaintColor);
                window.SetLineWidth(LineWidth);
                window.SetDraw("margin");
                window.DispCircle(new HTuple(Center.Y), new HTuple(Center.X), new HTuple(Radius));
            }
            else
            {
                if (!IsSelected)
                {
                    window.SetColor(PaintColor);
                    window.SetLineWidth(LineWidth);
                    window.SetDraw("margin");
                    window.DispCircle(new HTuple(Center.Y), new HTuple(Center.X), new HTuple(Radius));
                    window.SetColor("yellow");
                    float len = lenConvert(5);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X + Radius), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y - Radius), new HTuple(Center.X), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X - Radius), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y + Radius), new HTuple(Center.X), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X), 0, len, len);
                }
                else
                {
                    window.SetColor("orange");
                    window.SetLineWidth(1);
                    window.SetDraw("margin");
                    window.DispCircle(new HTuple(Center.Y), new HTuple(Center.X), new HTuple(Radius));
                    window.SetColor("red");
                    float len = lenConvert(5);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X + Radius), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y - Radius), new HTuple(Center.X), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X - Radius), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y + Radius), new HTuple(Center.X), 0, len, len);
                    window.DispRectangle2(new HTuple(Center.Y), new HTuple(Center.X), 0, len, len);
                }
            }
        }
        public override PositionNB PointOnShape(PointF testPoint, Func<float, float> lenConvert)
        {
            double dcenter = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(Center.Y), new HTuple(Center.X));
            double dleft = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(Center.Y), new HTuple(Center.X - Radius));
            double dup = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(Center.Y - Radius), new HTuple(Center.X));
            double dright = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(Center.Y), new HTuple(Center.X + Radius));
            double ddown = HMisc.DistancePp(new HTuple(testPoint.Y), new HTuple(testPoint.X), new HTuple(Center.Y + Radius), new HTuple(Center.X));

            distance2Handle = (int)lenConvert(10);

            if (dcenter < distance2Handle)
                return PositionNB.In;
            else if (dright < distance2Handle)
                return PositionNB.Right;
            else if (dup < distance2Handle)
                return PositionNB.Up;
            else if (dleft < distance2Handle)
                return PositionNB.Left;
            else if (ddown < distance2Handle)
                return PositionNB.Down;
            else
                return PositionNB.Out;
        }
        public override void Change(PointF point)
        {
            switch (ChangeModel)
            {
                case PositionNB.In:
                    float dx = point.X - Center.X;
                    float dy = point.Y - Center.Y;
                    this.Center = new PointF(Center.X + dx, Center.Y + dy);
                    break;
                case PositionNB.Create:
                case PositionNB.Left:
                case PositionNB.Right:
                case PositionNB.Up:
                case PositionNB.Down:
                case PositionNB.LeftUp:
                case PositionNB.RightDown:
                case PositionNB.LeftDown:
                case PositionNB.RightUp:
                    this.Radius = (float)Math.Sqrt(Math.Pow(point.X - Center.X, 2) + Math.Pow(point.Y - Center.Y, 2));
                    break;
            }
        }
        public override HObject ToRegion()
        {
            HRegion reg = new HRegion();
            try
            {
                reg.GenCircle((double)Center.Y, (double)Center.X, (double)Radius);
            }
            catch
            {

            }
            return reg;
        }
        public override PointF GetCenter()
        {
            return this.Center;
        }
        public override void ToXmlNode(out Dictionary<string, object> attributes, out Dictionary<string, object> nodes)
        {
            attributes = new Dictionary<string, object>();
            attributes.Add("Type", TypeName.ToString());
            attributes.Add("Color", PaintColor);
            attributes.Add("LineWidth", LineWidth);
            attributes.Add("Operator", RegOperator.ToString());
            nodes = new Dictionary<string, object>();
            nodes.Add("Center", Center.X.ToString("0.000") + "," + Center.Y.ToString("0.000"));
            nodes.Add("Radius", Radius.ToString("0.000"));
            nodes.Add("Alias", string.IsNullOrEmpty(Alias) ? "" : Alias);
        }
        public override void FromXmlNode(XmlNode node)
        {
            RegOperator = (ShapeOperator)Enum.Parse(typeof(ShapeOperator), node.Attributes["Operator"].Value);
            PaintColor = node.Attributes["Color"].Value;
            LineWidth = Int32.Parse(node.Attributes["LineWidth"].Value);
            foreach (XmlNode xn in node.ChildNodes)
            {
                if (xn.Name == "Center")
                {
                    Center = new PointF(float.Parse(xn.InnerText.Split(',')[0]),
                                        float.Parse(xn.InnerText.Split(',')[1]));
                }
                else if (xn.Name == "Radius")
                {
                    Radius = float.Parse(xn.InnerText);
                }
                else if (xn.Name == "Alias")
                {
                    Alias = xn.InnerText;
                }
            }
        }
    }
}
